package com.zbkj.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.constants.ProductConstants;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.card.StoreGift;
import com.zbkj.common.model.product.StoreProduct;
import com.zbkj.common.model.product.StoreProductAttr;
import com.zbkj.common.model.product.StoreProductAttrValue;
import com.zbkj.common.model.product.StoreProductDescription;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.*;
import com.zbkj.common.response.*;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.utils.DateUtil;
import com.zbkj.service.dao.StoreGiftDao;
import com.zbkj.service.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 礼品卡商品配置服务实现
 *
 * @author Swallows
 * @date 2022-10-12 14:27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StoreGiftServiceImpl extends ServiceImpl<StoreGiftDao, StoreGift> implements StoreGiftService {

    private final StoreGiftDao storeGiftDao;
    private final SystemAttachmentService systemAttachmentService;
    private final StoreProductDescriptionService storeProductDescriptionService;
    private final StoreProductService storeProductService;
    private final StoreProductAttrService storeProductAttrService;
    private final StoreProductAttrValueService storeProductAttrValueService;
    private final TransactionTemplate transactionTemplate;

    @Override
    public Boolean operationStock(Integer id, Integer num, String type) {

        UpdateWrapper<StoreGift> updateWrapper = new UpdateWrapper<>();
        if (type.equals("add")) {
            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
            updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
        }
        if (type.equals("sub")) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
            updateWrapper.setSql(StrUtil.format("quota = quota - {}", num));
            // 扣减时加乐观锁保证库存不为负
            updateWrapper.last(StrUtil.format(" and (quota - {} >= 0)", num));
        }
        updateWrapper.eq("id", id);
        boolean update = update(updateWrapper);
        if (!update) {
            throw new CrmebException("更新商品库存失败！商品id = " + id);
        }
        return update;
    }

    @Override
    public StoreGift getByIdException(Integer id) {

        LambdaQueryWrapper<StoreGift> lqw = Wrappers.lambdaQuery();
        lqw.eq(StoreGift::getId, id);
        lqw.eq(StoreGift::getIsDel, false);
        lqw.eq(StoreGift::getIsShow, true);

        StoreGift gift = storeGiftDao.selectOne(lqw);
        if (ObjectUtil.isNull(gift) || gift.getIsDel()) {
            throw new CrmebException("查找的礼品不存在或者已删除");
        }
        return gift;
    }

    @Override
    public StoreGiftDetailResponse getDetailH5(Integer giftId) {

//        1.获取礼品信息
        StoreGift storeGift = storeGiftDao.selectById(giftId);
//        2.判断该礼品是否存在
        if (ObjectUtil.isNull(storeGift) || storeGift.getIsDel()) {
            throw new CrmebException("未找到对应礼品信息");
        }
        if (!storeGift.getIsShow()) {
            throw new CrmebException("该礼品已下架");
        }

        StoreGiftDetailResponse productDetailResponse = new StoreGiftDetailResponse();
        StoreGiftDetailH5Response detailH5Response = new StoreGiftDetailH5Response();
        BeanUtils.copyProperties(storeGift, detailH5Response);
        detailH5Response.setSliderImage(storeGift.getImages());
        detailH5Response.setStoreName(storeGift.getTitle());
        detailH5Response.setStoreInfo(storeGift.getInfo());

//        详情
        StoreProductDescription productDescription = storeProductDescriptionService.getByProductIdAndType(giftId, Constants.PRODUCT_TYPE_GIFT);
        if (ObjectUtil.isNotNull(productDescription)) {
            detailH5Response.setContent(ObjectUtil.isNull(productDescription.getDescription()) ? "" : productDescription.getDescription());
        }

//        获取主商品信息
        StoreProduct storeProduct = storeProductService.getById(storeGift.getProductId());
//        主商品状态
        if (storeProduct.getIsDel()) {
            productDetailResponse.setMasterStatus("delete");
        } else if (!storeProduct.getIsShow()) {
            productDetailResponse.setMasterStatus("soldOut");
        } else if (storeProduct.getStock() <= 0) {
            productDetailResponse.setMasterStatus("sellOut");
        } else {
            productDetailResponse.setMasterStatus("normal");
        }

//        原商品销量（包含虚拟销量）
        detailH5Response.setSales(storeProduct.getSales());
        detailH5Response.setFicti(storeProduct.getFicti());

        productDetailResponse.setStoreGift(detailH5Response);

//        获取礼品规格
        List<StoreProductAttr> attrList = storeProductAttrService.getListByProductIdAndType(giftId, Constants.PRODUCT_TYPE_GIFT);
        productDetailResponse.setProductAttr(attrList);

//        根据规格设置sku
        HashMap<String, Object> skuMap = CollUtil.newHashMap();
//        获取主商品sku
        List<StoreProductAttrValue> storeProductAttrValues = storeProductAttrValueService.getListByProductIdAndType(storeGift.getProductId(), Constants.PRODUCT_TYPE_NORMAL);
//        获取礼品sku
        List<StoreProductAttrValue> giftAttrValues = storeProductAttrValueService.getListByProductIdAndType(giftId, Constants.PRODUCT_TYPE_GIFT);
        for (StoreProductAttrValue productAttrValue : giftAttrValues) {
            StoreProductAttrValueResponse atr = new StoreProductAttrValueResponse();
            List<StoreProductAttrValue> valueList = giftAttrValues.stream().filter(e -> productAttrValue.getSuk().equals(e.getSuk())).collect(Collectors.toList());
            if (CollUtil.isEmpty(valueList)) {
                BeanUtils.copyProperties(productAttrValue, atr);
            } else {
                BeanUtils.copyProperties(valueList.get(0), atr);
            }
            skuMap.put(atr.getSuk(), atr);
        }
        productDetailResponse.setProductValue(skuMap);

        return productDetailResponse;
    }

    @Override
    public List<StoreGiftH5Response> getEnableListByCardId(Integer cardId, PageParamRequest pageParamRequest) {

        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<StoreGift> lqw = Wrappers.lambdaQuery();
        lqw.eq(StoreGift::getIsDel, false);
        lqw.eq(StoreGift::getCardConfigId, cardId);
        lqw.eq(StoreGift::getIsShow, true);
        lqw.orderByDesc(StoreGift::getId);

        List<StoreGift> list = storeGiftDao.selectList(lqw);
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }

        List<StoreGiftH5Response> responses = new ArrayList<>();
        list.forEach(e -> {
            StoreGiftH5Response response = new StoreGiftH5Response();
            BeanUtils.copyProperties(e, response);
            response.setPercent(CrmebUtil.percentInstanceIntVal(e.getQuotaShow() - e.getQuota(), e.getQuotaShow()));
            responses.add(response);
        });
        return responses;
    }

    @Override
    public PageInfo<StoreGiftResponse> getList(StoreGiftSearchRequest request, PageParamRequest pageParamRequest) {

        Page<StoreGift> storeGiftPage = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<StoreGift> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StoreGift::getIsDel, false);
        if (StrUtil.isNotEmpty(request.getKeywords())) {
            lqw.and(i -> i.like(StoreGift::getProductId, request.getKeywords())
                    .or().like(StoreGift::getId, request.getKeywords())
                    .or().like(StoreGift::getTitle, request.getKeywords()));
        }
        if (ObjectUtil.isNotNull(request.getIsShow())) {
            lqw.eq(StoreGift::getIsShow, request.getIsShow() == 1);
        }
        lqw.orderByDesc(StoreGift::getIsShow, StoreGift::getId);
        List<StoreGift> storeGiftList = storeGiftDao.selectList(lqw);
        if (CollUtil.isEmpty(storeGiftList)) {
            return CommonPage.copyPageInfo(storeGiftPage, CollUtil.newArrayList());
        }

        List<StoreGiftResponse> storeGiftResponseList = storeGiftList.stream().map(storeGift -> {
            StoreGiftResponse storeGiftResponse = new StoreGiftResponse();
            BeanUtil.copyProperties(storeGift, storeGiftResponse);
            return storeGiftResponse;
        }).collect(Collectors.toList());

        return CommonPage.copyPageInfo(storeGiftPage, storeGiftResponseList);
    }

    @Override
    public Boolean addGift(StoreGiftRequest request) {

        if (!request.getSpecType()) {
            if (request.getAttrValue().size() > 1) {
                throw new CrmebException("单规格商品属性值不能大于1");
            }
        }

        StoreGift storeGift = new StoreGift();
        BeanUtil.copyProperties(request, storeGift);
        storeGift.setId(null);
        storeGift.setImage(systemAttachmentService.clearPrefix(request.getImage()));
        storeGift.setImages(systemAttachmentService.clearPrefix(request.getImages()));
        storeGift.setCreateTime(DateUtil.nowDateTime());
        storeGift.setUpdateTime(DateUtil.nowDateTime());

        List<StoreProductAttrValueAddRequest> attrValueAddRequestList = request.getAttrValue();
        // 计算价格
        StoreProductAttrValueAddRequest minAttrValue = attrValueAddRequestList.stream().min(Comparator.comparing(StoreProductAttrValueAddRequest::getPrice)).get();
        storeGift.setPrice(minAttrValue.getPrice());
        storeGift.setOtPrice(minAttrValue.getOtPrice());
        int quota = attrValueAddRequestList.stream().mapToInt(StoreProductAttrValueAddRequest::getQuota).sum();
        storeGift.setStock(quota);
        storeGift.setQuota(quota);
        storeGift.setQuotaShow(quota);
        storeGift.setSort(0);
        if (ObjectUtil.isNotNull(request.getSort())) {
            storeGift.setSort(request.getSort());
        }

        List<StoreProductAttrAddRequest> addRequestList = request.getAttr();
        List<StoreProductAttr> attrList = addRequestList.stream().map(e -> {
            StoreProductAttr attr = new StoreProductAttr();
            BeanUtils.copyProperties(e, attr);
            attr.setType(Constants.PRODUCT_TYPE_GIFT);
            return attr;
        }).collect(Collectors.toList());

        List<StoreProductAttrValue> attrValueList = attrValueAddRequestList.stream().map(e -> {
            StoreProductAttrValue attrValue = new StoreProductAttrValue();
            BeanUtils.copyProperties(e, attrValue);
            attrValue.setSuk(e.getSuk());
            attrValue.setQuota(e.getQuota());
            attrValue.setQuotaShow(e.getQuota());
            attrValue.setType(Constants.PRODUCT_TYPE_GIFT);
            attrValue.setImage(systemAttachmentService.clearPrefix(e.getImage()));
            return attrValue;
        }).collect(Collectors.toList());

        StoreProductDescription spd = new StoreProductDescription();
        spd.setDescription(request.getContent().length() > 0 ? systemAttachmentService.clearPrefix(request.getContent()) : "");
        spd.setType(Constants.PRODUCT_TYPE_GIFT);

        Boolean execute = transactionTemplate.execute(e -> {
            save(storeGift);

            attrList.forEach(attr -> attr.setProductId(storeGift.getId()));
            attrValueList.forEach(value -> value.setProductId(storeGift.getId()));
            storeProductAttrService.saveBatch(attrList);
            storeProductAttrValueService.saveBatch(attrValueList);

            spd.setProductId(storeGift.getId());
            storeProductDescriptionService.deleteByProductId(storeGift.getId(), Constants.PRODUCT_TYPE_GIFT);
            storeProductDescriptionService.save(spd);

            return Boolean.TRUE;
        });

        return execute;
    }

    @Override
    public Boolean updateGift(StoreGiftRequest request) {

        if (ObjectUtil.isNull(request.getId())) {
            throw new CrmebException("礼品卡兑换商品id不能为空");
        }

        StoreGift existGift = getById(request.getId());
        if (ObjectUtil.isNull(existGift) || existGift.getIsDel()) {
            throw new CrmebException("礼品卡兑换不存在");
        }
        if (existGift.getIsShow()) {
            throw new CrmebException("活动开启中，商品不支持修改");
        }

        StoreGift storeGift = new StoreGift();
        BeanUtil.copyProperties(request, storeGift);

        // 头图、轮播图
        storeGift.setImage(systemAttachmentService.clearPrefix(request.getImage()));
        storeGift.setImages(systemAttachmentService.clearPrefix(request.getImages()));

        List<StoreProductAttrValueAddRequest> attrValueAddRequestList = request.getAttrValue();
        // 计算价格
        StoreProductAttrValueAddRequest minAttrValue = attrValueAddRequestList.stream().min(Comparator.comparing(StoreProductAttrValueAddRequest::getPrice)).get();
        storeGift.setPrice(minAttrValue.getPrice());
        storeGift.setOtPrice(minAttrValue.getOtPrice());
        int quota = attrValueAddRequestList.stream().mapToInt(StoreProductAttrValueAddRequest::getQuota).sum();
        storeGift.setStock(quota);
        storeGift.setQuota(quota);
        storeGift.setQuotaShow(quota);
        storeGift.setSort(0);
        if (ObjectUtil.isNotNull(request.getSort())) {
            storeGift.setSort(request.getSort());
        }

        // attr部分
        List<StoreProductAttrAddRequest> addRequestList = request.getAttr();
        List<StoreProductAttr> attrAddList = CollUtil.newArrayList();
        List<StoreProductAttr> attrUpdateList = CollUtil.newArrayList();
        addRequestList.forEach(e -> {
            StoreProductAttr attr = new StoreProductAttr();
            BeanUtils.copyProperties(e, attr);
            if (ObjectUtil.isNull(attr.getId())) {
                attr.setProductId(storeGift.getId());
                attr.setType(Constants.PRODUCT_TYPE_GIFT);
                attrAddList.add(attr);
            } else {
                attr.setProductId(storeGift.getId());
                attr.setIsDel(false);
                attrUpdateList.add(attr);
            }
        });

        // attrValue部分
        List<StoreProductAttrValue> attrValueAddList = CollUtil.newArrayList();
        List<StoreProductAttrValue> attrValueUpdateList = CollUtil.newArrayList();
        attrValueAddRequestList.forEach(e -> {
            StoreProductAttrValue attrValue = new StoreProductAttrValue();
            BeanUtils.copyProperties(e, attrValue);
            attrValue.setSuk(e.getSuk());
            attrValue.setImage(systemAttachmentService.clearPrefix(e.getImage()));
            attrValue.setQuota(e.getQuota());
            attrValue.setQuotaShow(e.getQuota());
            if (ObjectUtil.isNull(attrValue.getId())) {
                attrValue.setProductId(storeGift.getId());
                attrValue.setType(Constants.PRODUCT_TYPE_GIFT);
                attrValueAddList.add(attrValue);
            } else {
                attrValue.setProductId(storeGift.getId());
                attrValue.setIsDel(false);
                attrValueUpdateList.add(attrValue);
            }
        });

        // 处理富文本
        StoreProductDescription spd = new StoreProductDescription();
        spd.setDescription(request.getContent().length() > 0 ? systemAttachmentService.clearPrefix(request.getContent()) : "");
        spd.setType(Constants.PRODUCT_TYPE_GIFT);
        spd.setProductId(request.getId());

        Boolean execute = transactionTemplate.execute(e -> {
            storeGiftDao.updateById(storeGift);

            // 先删除原用attr+value
            storeProductAttrService.deleteByProductIdAndType(storeGift.getId(), Constants.PRODUCT_TYPE_GIFT);
            storeProductAttrValueService.deleteByProductIdAndType(storeGift.getId(), Constants.PRODUCT_TYPE_GIFT);

            if (CollUtil.isNotEmpty(attrAddList)) {
                storeProductAttrService.saveBatch(attrAddList);
            }
            if (CollUtil.isNotEmpty(attrUpdateList)) {
                storeProductAttrService.saveOrUpdateBatch(attrUpdateList);
            }

            if (CollUtil.isNotEmpty(attrValueAddList)) {
                storeProductAttrValueService.saveBatch(attrValueAddList);
            }
            if (CollUtil.isNotEmpty(attrValueUpdateList)) {
                storeProductAttrValueService.saveOrUpdateBatch(attrValueUpdateList);
            }

            storeProductDescriptionService.deleteByProductId(storeGift.getId(), Constants.PRODUCT_TYPE_GIFT);
            storeProductDescriptionService.save(spd);

            return Boolean.TRUE;
        });

        return execute;
    }

    @Override
    public Boolean deleteById(Integer id) {

        StoreGift existGift = getById(id);
        if (ObjectUtil.isNull(existGift) || existGift.getIsDel()) {
            throw new CrmebException("礼品卡兑换不存在");
        }
        if (existGift.getIsShow()) {
            throw new CrmebException("活动开启中，商品不支持修改");
        }

        StoreGift storeGift = new StoreGift();
        storeGift.setId(id);
        storeGift.setIsDel(true);
        return updateById(storeGift);
    }

    @Override
    public StoreProductInfoResponse getAdminDetail(Integer id) {

        StoreGift storeGift = getById(id);
        if (ObjectUtil.isNull(storeGift) || storeGift.getIsDel()) {
            throw new CrmebException("未找到对应商品信息");
        }
        StoreProductInfoResponse storeProductResponse = new StoreProductInfoResponse();
        BeanUtils.copyProperties(storeGift, storeProductResponse);

        // 查询attr
        List<StoreProductAttr> attrs = storeProductAttrService.getListByProductIdAndType(id, Constants.PRODUCT_TYPE_PINGTUAN);
        storeProductResponse.setAttr(attrs);
        storeProductResponse.setSliderImage(String.join(",", storeGift.getImages()));

        boolean specType = attrs.size() > 1;
        storeProductResponse.setSpecType(specType);

        List<StoreProductAttrValue> comAttrValueList = storeProductAttrValueService.getListByProductIdAndType(id, ProductConstants.PRODUCT_TYPE_GIFT);
        // 查询主商品sku
        List<StoreProductAttrValue> attrValueList = storeProductAttrValueService.getListByProductIdAndType(storeGift.getProductId(), Constants.PRODUCT_TYPE_NORMAL);

        List<AttrValueResponse> valueResponseList = attrValueList.stream().map(e -> {
            AttrValueResponse valueResponse = new AttrValueResponse();
            Integer tempId = 0;
            for (StoreProductAttrValue value : comAttrValueList) {
                if (value.getSuk().equals(e.getSuk())) {
                    tempId = value.getId();
                    BeanUtils.copyProperties(value, valueResponse);
                    break;
                }
            }
            if (tempId.equals(0)) {
                BeanUtils.copyProperties(e, valueResponse);
                valueResponse.setId(null);
            } else {
                valueResponse.setId(tempId);
            }
            return valueResponse;
        }).collect(Collectors.toList());
        storeProductResponse.setAttrValue(valueResponseList);

        StoreProductDescription sd = storeProductDescriptionService.getByProductIdAndType(id, Constants.PRODUCT_TYPE_PINGTUAN);
        if (ObjectUtil.isNotNull(sd)) {
            storeProductResponse.setContent(ObjectUtil.isNull(sd.getDescription()) ? "" : sd.getDescription());
        }
        return storeProductResponse;
    }

    @Override
    public Boolean updateGiftShow(Integer id, Boolean isShow) {

        StoreGift existGift = getById(id);
        if (ObjectUtil.isNull(existGift) || existGift.getIsDel()) {
            throw new CrmebException("拼团商品不存在");
        }
        if (isShow) {
            // 判断商品是否存在
            StoreProduct product = storeProductService.getById(existGift.getProductId());
            if (ObjectUtil.isNull(product)) {
                throw new CrmebException("关联的商品已删除，无法开启");
            }
        }

        StoreGift storeGift = new StoreGift();
        storeGift.setId(id);
        storeGift.setIsShow(isShow);
        storeGift.setUpdateTime(DateUtil.nowDateTime());
        return updateById(storeGift);
    }
}
